/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pa165.mushroom.website.client.web;

import cz.muni.fi.pa165.mushroom.website.client.dto.ForestDto;
import cz.muni.fi.pa165.mushroom.website.client.dto.MushroomDto;
import cz.muni.fi.pa165.mushroom.website.client.validator.ForestValidator;
import java.io.IOException;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.ModelAndView;

/**
 *
 * @author roman
 */
@Controller
@RequestMapping("/forest")
public class ForestClientController {
    
    private String remoteHost = "http://localhost:8080/pa165/rest/forest/";
    
    @Autowired
    private RestTemplate rest;
    
    private ForestDto addedForestBackingBean;
    private ForestDto editedForestBackingBean;
    
    @Autowired
    @Qualifier("forestValidator")
    private ForestValidator forestValidator;

    @PostConstruct
    public void init() {
        addedForestBackingBean = new ForestDto();
    }

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView renderList() {
        String url = remoteHost + "listForests";        
        List<ForestDto> list = rest.getForObject(url,List.class);       
        ModelAndView mav = new ModelAndView();
        mav.addObject("forests", list);
        mav.setViewName("forest/list");
        return mav;
    }
    
    @RequestMapping(value = "mushrooms/{id}", method = RequestMethod.GET)
    public ModelAndView listFoundMushrooms(@PathVariable String id) {
        String url = remoteHost + "getMushrooms/" + id; 
        
        List<MushroomDto> list = rest.getForObject(url,List.class);       
        ModelAndView mav = new ModelAndView();
        mav.addObject("mushrooms", list);
        mav.setViewName("forest/mushrooms");
        return mav;
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public ModelAndView renderDetail(@PathVariable String id) {
        String url = remoteHost + "getForest/" + id;
        ModelAndView mav = new ModelAndView();
        mav.addObject("forest", getRemoteForest(id));
        mav.setViewName("forest/detail");
        return mav;
    }

    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public ModelAndView renderAdd() {
        ModelAndView mav = new ModelAndView();
        mav.addObject("addedForest", addedForestBackingBean);
        mav.setViewName("forest/add");
        return mav;
    }

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String addForest(@ModelAttribute("addedForest") ForestDto forestDto,
            BindingResult result, ModelMap modelMap) {
        forestValidator.validate(forestDto, result);
        String url = remoteHost + "createForest/";
        if (result.hasErrors()) {
            addedForestBackingBean = forestDto;
            modelMap.put(BindingResult.class.getName() + "addedForest", result);
            return "forest/add";
        } else {
            rest.postForObject(url, forestDto, ForestDto.class);
            return "redirect:/forest/add/success";
        }
    }

    @RequestMapping(value = "/add/success", method = RequestMethod.GET)
    public ModelAndView addSuccess() {
        ModelAndView mav = new ModelAndView();
        mav.addObject("successMessage", "forest.add.success");
        mav.setViewName("forest/success");
        return mav;
    }

    @RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
    public ModelAndView renderEdit(@PathVariable String id) {
        ModelAndView mav = new ModelAndView();
        editedForestBackingBean = getRemoteForest(id);
        mav.addObject("editedForest", editedForestBackingBean);
        mav.setViewName("forest/edit");
        return mav;
    }

    @RequestMapping(value = "/edit/{id}", method = RequestMethod.POST)
    public String editForest(@ModelAttribute("editedForest") ForestDto editedForest,
            @PathVariable String id, BindingResult result, ModelMap modelMap) {
        forestValidator.validate(editedForest, result);
        String url = remoteHost + "editForest";
        if (result.hasErrors()) {
            modelMap.put("editedForest", editedForest);
            modelMap.put(BindingResult.class.getName() + "editedForest", result);
            return "forest/edit";
        } else {
            rest.put(url, editedForest);
            return "redirect:/forest/edit/success";
        }
    }

    @RequestMapping(value = "/edit/success", method = RequestMethod.GET)
    public ModelAndView editSuccess() {
        ModelAndView mav = new ModelAndView();
        mav.addObject("successMessage", "forest.edit.success");
        mav.setViewName("forest/success");
        return mav;
    }

    @RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
    public ModelAndView renderDelete(@PathVariable String id) {
        ModelAndView mav = new ModelAndView();
        ForestDto deletedForest = getRemoteForest(id);
        mav.addObject("deletedForest", deletedForest);
        mav.setViewName("forest/delete");
        return mav;
    }

    @RequestMapping(value = "/delete/{id}", method = RequestMethod.POST)
    public String deleteForest(@PathVariable String id) {
        String url = remoteHost + "deleteForest/" + id;
        rest.delete(url);
        return "redirect:/forest/delete/success";
    }

    @RequestMapping(value = "/delete/success", method = RequestMethod.GET)
    public ModelAndView deleteSuccess() {
        ModelAndView mav = new ModelAndView();
        mav.addObject("successMessage", "forest.delete.success");
        mav.setViewName("forest/success");
        return mav;
    }

    @ExceptionHandler(RestClientException.class)
    public ModelAndView badFormat(RestClientException ex) {
        ModelAndView mav = new ModelAndView();
        mav.addObject("error", "Remote host " + remoteHost + " returned error code:");
        if (ex.contains(IOException.class)) {
            mav.addObject("code", "503 Service Unavailable");
        } else {
            mav.addObject("code", ex.getMessage());
        }
        mav.setViewName("forest/error");

        return mav;
    }

    private ForestDto getRemoteForest(String id) throws RestClientException {
        String url = remoteHost + "getForest/" + id;
        ForestDto resp = rest.getForObject(url, ForestDto.class);       
        
        return resp;
    }
}
